import { RFile, GetJson, PathChoose, AskQuestions, AskOutPut } from '../util.js'
import chalk from 'chalk';
import fs from 'fs';
import path from 'path';
import { FormatJson, Beautify, FormatInterface, FormatPathName, FormatParmas, FormatBody, FormatResponse, FormatExampleParmas } from '../Format.js'



/**
 * 输出文件
 *
 * @param { String } filePath 文件路径
 * @param { String } content 文件内容
 */
const WriteFile = (filePath, content) => {
    fs.writeFile(path.resolve(filePath), content, 'utf-8', function (err) {
        if (err) {
            console.log(chalk.red(err));
        } else {
            console.log(chalk.greenBright(filePath + ' : 输出成功!'));
        }
    });
};


/**
 * 输出 TS 命名空间
 *
 * @param { Object } data Swagger JSON 参数
 * @param { String } FileName 文件名
 * @return { String } 
 */
const FormatInterfaceFile = (data, FileName) => {
    var Data = `declare namespace ${FileName} {\n`;
    for (const key in data.components.schemas) {
        const element = data.components.schemas[key];
        Data += FormatInterface(element, key);
    };
    Data += `\n}`;
    return Data;
}


/**
 * 获取文件名
 *
 * @param { Object } config Swagger JSON 参数
 * @return { String } 
 */
const GetFileName = (config) => {
    var paths = config.paths;
    for (const key in paths) {
        const element = paths[key];
        for (const key in element) {
            const item = element[key];
            return item.tags[0]
        };
    }
}


/**
 * 格式化 Ajax 参数
 *
 * @param { Object } data Swagger JSON 参数
 * @param { Object } config 配置参数
 * @param { String } FileName 文件名
 * @param { Array } IgnorePathArray 需要跳过的字段
 * @return { String } 
 */
const FormatAJAX = (data, config, FileName, IgnorePathArray) => {
    var pathMapping = {};
    var STR = `${config.formatModuleString}
export default {\n
    // ${data.info.title || ''} ${data.info.description ? '( ' + data.info.description + ' )' : ''}

`;

    for (const path in data.paths) {
        const item = data.paths[path];
        for (const type in item) {
            const single = item[type];
            const key = single.tags[0] || '';

            var pathkey = FormatPathName(path, key, type, IgnorePathArray, pathMapping);
            var header = single.parameters && FormatParmas(single.parameters, 'header', FileName);
            var query = single.parameters && FormatParmas(single.parameters, 'query', FileName);
            var Body = single?.requestBody?.content?.['application/json']?.schema && FormatBody(single?.requestBody?.content?.['application/json'], FileName);
            var Response = single?.responses?.['200']?.content?.['application/json']?.schema && FormatResponse(single?.responses?.['200']?.content?.['application/json'], FileName);
            var parmas = [];
            query && parmas.push('query: ' + query);
            Body && parmas.push('body: ' + Body);
            // Response && parmas.push('body: ' + Body);
            parmas.push('loading?: boolean');
            header && parmas.push('header?: ' + header);

            var BodyJson = single?.requestBody?.content?.['application/json']?.schema && FormatJson(single?.requestBody?.content?.['application/json'].schema, data.components.schemas, FileName);
            var ResponseJson = single?.responses?.['200']?.content?.['application/json']?.schema && FormatJson(single?.responses?.['200']?.content?.['application/json'].schema, data.components.schemas, FileName);

            if (BodyJson) {
                BodyJson = BodyJson.replace(/,$/gi, "");
                BodyJson = `     * var Body${Body ? ':' + Body : ''} = ${Beautify(BodyJson)}\n`;
                BodyJson = BodyJson.replace(/\n/g, '\n     * ') + '\n     *\n';
            }

            if (ResponseJson) {
                ResponseJson = ResponseJson.replace(/,$/gi, "");
                ResponseJson = `     * var Response${Response ? ':' + Response : ''} = ${Beautify(ResponseJson)}\n`;
                ResponseJson = ResponseJson.replace(/\n/g, '\n     * ') + '\n     *\n';
            }
            var QueryStr = '';
            if (query) {
                QueryStr = `     * interface QueryParmas = ${single.parameters && FormatExampleParmas(single.parameters, 'query', FileName)}\n`;
                QueryStr = QueryStr.replace(/\n/g, '\n     * ') + '\n     *\n';
            }
            var HeaderStr = '';
            if (header) {
                HeaderStr = `     * interface HeaderParmas = ${single.parameters && FormatExampleParmas(single.parameters, 'header', FileName)}\n`;
                HeaderStr = HeaderStr.replace(/\n/g, '\n     * ') + '\n     *\n';
            }

            var AxioStaing = `    /**
     * ${single.summary || ''}
     * 
${query ? `     * @param { object } query Url参数\n` : ''}${Body ? `     * @param { ${Body} } Body Body参数\n` : ''}     * @param { boolean } loading 是否显示loading
${header ? `     * @param { object } header header参数\n` : ''}     * @return { Promise } 接口异步传输对象
     * @example 
     *
${QueryStr ? QueryStr : ''}${HeaderStr ? HeaderStr : ''}${BodyJson ? BodyJson : ''}${ResponseJson ? ResponseJson : ''}     * 
     */
    '${pathkey}': function (${parmas.join(', ')}) {
        return request.${type}('${path}', ${query ? 'query' : '{}'}, ${Body ? 'Body' : '{}'}, 'pro', loading, ${header ? 'header' : '{}'})
    },\n
`
            STR += AxioStaing;
        };
    };

    STR += '\n\n}'

    return STR;
}

/**
 * 导出文件
 *
 * @param { Object } data Swagger JSON 对象
 * @param { Object } config Swagger 参数配置
 */
const ExportsFile = (data, config, OutPut) => {
    var FileName = GetFileName(data);
    var IgnorePathArray = config.IgnorePath || [];

    var TypeFolder = OutPut + '/type/';
    if (!fs.existsSync(TypeFolder)) fs.mkdirSync(TypeFolder);

    var InterfacePath = OutPut + '/type/' + FileName + '.d.ts';
    WriteFile(InterfacePath, FormatInterfaceFile(data, FileName));

    var AJAXPath = OutPut + '/' + FileName + '.ts';
    WriteFile(AJAXPath, FormatAJAX(data, config, FileName, IgnorePathArray));
};





/**
 * 执行导出配置
 *
 * @param { Object } config Swagger 参数配置
 */
export const Run = async config => {
    let DocPath = await PathChoose(config.path);
    const Doclist = await GetJson(DocPath._index);
    var QuestionsList = [];
    Doclist.forEach(ele => {
        QuestionsList.push(ele.name + '(' + chalk.yellow(ele.key) + ')');
    })
    const answers = await AskQuestions(QuestionsList);
    if (answers._index == 0) {
        Doclist.forEach(async ele => {
            var wrihteDoc = await RFile(ele.url);
            ExportsFile(wrihteDoc, config, config.apiPath);
        });
    } else {
        var selectDoc = Doclist[answers._index - 1];
        var wrihteDoc = await RFile(selectDoc.url);
        ExportsFile(wrihteDoc, config, config.apiPath);
    };
}



